﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using DG.Tweening;
using Lv1;

public class StarBox : MonoBehaviour
{
    //全局触摸标记，这个值不为0，则玩家不能进行消除操作
    public static int forbidTouchFlags;
    public static int generateSpecialStarFlag;
    public static int destroyingStarFlag;
    public static int checkingStarTurnFlag;
    public static int fallingStarFlag;
    public static int customerLeavingFlag;
    public static int castingSkillFlag;

    private int numX = 7;
    private int numY = 7;
    private bool canTouch;
    private bool isLinking;
    private bool isGameOver;
    //记录debuff已经选择到列表中的哪一个位置了
    private int debuffIndex;
    private int Turn { get; set; }

    public static Star[,] starTable;
    public static GameObject[,] bgBlocks;
    private SpriteRenderer boxClip;
    private int destroySoundIndex;

    private List<Sys_Star> starsColor;
    //爆炸宝石的列表，游戏初始化时，保存好列表
    private List<Sys_Star> boomStars = new List<Sys_Star>();
    private Dictionary<int, int> colorCount = new Dictionary<int, int>();
    [HideInInspector]
    public Sys_Stage curStage;
    //特殊状态宝石列表，这个列表只要不为空，就会生成特殊宝石
    public static List<Sys_Star> SpecialStars = new List<Sys_Star>();
    private List<Star> starLink = new List<Star>();

    //标示爆炸宝石生成的圆圈，int对应相应的消除数级，GameObject对应爆炸粒子特效对象
    private Dictionary<int, GameObject> boomCircleDic = new Dictionary<int, GameObject>();
    //爆炸波及的背景块，都保存在列表中，用完了，要清除掉
    private GameObject[,] boomRangeSprites;
    //这个标记这个位置有几个爆炸特效了，虽然只会有一个特效显示，但是这个值不为0，则不应该清除爆炸特效
    private int[,] boomRangeSpritesCount;

    public Player m_Player;
    public Girl m_Girl;

    public GameObject m_Debuff;
    public Text m_EnemyTurnText;

    public int NumX
    {
        get
        {
            return this.numX;
        }
    }

    public int NumY
    {
        get
        {
            return this.numY;
        }
    }

    public bool IsGameOver
    {
        get
        {
            return isGameOver;
        }
    }

    public bool IsCanTouch
    {
        get
        {
            return canTouch;
        }
    }

    public List<Sys_Star> StarsColor
    {
        get
        {
            return starsColor;
        }
    }

    public Dictionary<int, int> ColorCount
    {
        get
        {
            return this.colorCount;
        }
    }

    public bool IsGuideStage
    {
        get
        {
            return curStage != null && curStage.Id == 10000;
        }
    }

    void Awake()
    {
        boxClip = GetComponent<SpriteRenderer>();
    }

    // Use this for initialization
    void Start()
    {
        ConfigController.Instance.Init();
        //下载完文件，重新进游戏
        //GlobalData.Init();
        curStage = ConfigController.Instance.GetConfig<Sys_Stage>(1);

        if (IsGuideStage)
        {
            numX = 5;
            numY = 7;
        }
        else
        {
            numX = 8;
            numY = 8;
        }

        InitBackground();
        InitBgBlock();

        StartCoroutine(InitGame());
    }

    // Update is called once per frame
    void Update()
    {
        boxClip.enabled = forbidTouchFlags != 0 || checkingStarTurnFlag != 0
            || generateSpecialStarFlag != 0 || customerLeavingFlag != 0
            || fallingStarFlag != 0 || isGameOver;

        canTouch = !boxClip.enabled;

        if (forbidTouchFlags < 0)
        {
            print("Error! forbidTouchFlags < 0 !!!!");
        }


        //能点击，才能检测奖励宝石生成，因为奖励宝石生成过程中，是禁止点击的，这样，可以保证宝石轮流生成
        if (canTouch && SpecialStars.Count > 0)
        {
            StartCoroutine(CreateSpecialStar());
        }

        if (Input.GetMouseButtonDown(0))
        {
            if (TouchCheck.IsPointerOverUIObject())
            {

            }
            else
            {
                //Debug.Log("没有触摸在UI上");  
                MouseOnStar();
            }


        }

        if (Input.GetMouseButtonUp(0))
        {
            isLinking = false;
            if (canTouch)
            {
                StartCoroutine(Link());
            }
        }

        //正在划线连接
        if (isLinking && canTouch)
        {
            MouseOnStar();
        }
    }

    void InitFlags()
    {
        forbidTouchFlags = 0;
        generateSpecialStarFlag = 0;
        destroyingStarFlag = 0;
        checkingStarTurnFlag = 0;
        fallingStarFlag = 0;
        customerLeavingFlag = 0;
        castingSkillFlag = 0;
    }

    IEnumerator InitGame()
    {
        //messagePanel.transform.localScale = Vector3.zero;
        InitFlags();
        destroySoundIndex = 1;
        isGameOver = false;
        colorCount.Clear();
        //保存爆炸范围的遮罩。每个宝石位置都会有一个
        boomRangeSprites = new GameObject[numX, numY];
        boomRangeSpritesCount = new int[numX, numY];
        SpecialStars.Clear();
        //resultPanel[0].SetActive(false);
        //resultPanel[1].SetActive(false);

        string[] colors = curStage.AppearStar.Split(',');
        starsColor = new List<Sys_Star>();
        for (int i = 0; i < colors.Length; i++)
        {
            starsColor.Add(ConfigController.Instance.GetConfig<Sys_Star>(int.Parse(colors[i])));
            colorCount.Add(int.Parse(colors[i]), 0);
        }

        //保存爆炸宝石列表
        boomStars.Clear();
        var starData = ConfigController.Instance.GetConfigs<Sys_Star>();
        foreach (var data in starData)
        {
            if (data.Value.RequireDestroyNum > 0)
            {
                boomStars.Add(data.Value);
            }
        }
        debuffIndex = 0;
        //初始化玩家
        m_Player.GetComponent<Character>().Init(ConfigController.Instance.GetConfig<Sys_Role>(1));
        //初始化对手
        m_Girl.GetComponent<Character>().Init(ConfigController.Instance.GetConfig<Sys_Role>(2));

        StartCoroutine(CheckDebuffTurn());
        //InitSkills();
        ClearStarTable();
        InitStarTable();

        while (fallingStarFlag != 0)
        {
            yield return null;
        }
        //StartCoroutine(Countdown());
    }

    //void InitSkills()
    //{
    //    CheckBottomSkills();

    //    var skillData = GlobalData.GameCfgData[GlobalData.SYS_SKILL];
    //    //触发技能数据
    //    List<Dictionary<string, string>> triggerSkillData = new List<Dictionary<string, string>>();
    //    foreach (var data in skillData)
    //    {
    //        if (data.Value["triggerType"] == "0")
    //        {
    //            continue;
    //        }
    //        triggerSkillData.Add(data.Value);
    //    }

    //    for (int i = 0; i < triggerSkills.Length; i++)
    //    {
    //        triggerSkills[i].GetComponent<Skill>().InitSKill = int.Parse(triggerSkillData[i]["id"]);
    //        CheckSkillUseful(triggerSkills[i]);
    //    }

    //    skillProgress.Init(0, float.Parse(curStage["totalSkillProgress"]));
    //    skillProgress.OnProgress = OnTriggerSkillProgressFull;
    //    ResetSkillProgress();
    //}

    //public void CheckBottomSkills()
    //{
    //    //底部技能数据
    //    List<Dictionary<string, string>> bottomSkillData = new List<Dictionary<string, string>>();
    //    Dictionary<int, Dictionary<string, string>> skillData = GlobalData.GameCfgData[GlobalData.SYS_SKILL];
    //    foreach (var data in skillData)
    //    {
    //        if (data.Value["triggerType"] == "0")
    //        {
    //            bottomSkillData.Add(data.Value);
    //        }
    //    }


    //    for (int i = 0; i < bottomSkills.Length; i++)
    //    {
    //        bottomSkills[i].GetComponent<Skill>().InitSKill = int.Parse(bottomSkillData[i]["id"]);
    //        CheckSkillUseful(bottomSkills[i]);
    //    }
    //}

    //public void CheckSkillUseful(GameObject skillObj)
    //{
    //    Image img = skillObj.GetComponent<Image>();
    //    Skill skill = skillObj.GetComponent<Skill>();
    //    string image = "Skills/" + skill.Data["image"];
    //    bool isGray = false;
    //    if (!isGray && IsGuideStage && skill.Data["triggerType"] == "0")
    //    {
    //        image += "_1";
    //        isGray = true;
    //    }

    //    if (!isGray && skill.Data["cost"] != "0")
    //    {
    //        string[] values = skill.Data["cost"].Split(':');
    //        if (!UserData.Instance.Data.isPropEnough(int.Parse(values[0]), int.Parse(values[1])))
    //        {
    //            image += "_1";
    //            isGray = true;
    //        }
    //    }

    //    if (!isGray && skill.Data["type"] == "3")
    //    {
    //        //如果没有异常宝石，则摧毁异常宝石的技能不能点击，替换成灰色图片
    //        if (GetExistSpecialStars().Count == 0)
    //        {
    //            image += "_1";
    //            isGray = true;
    //        }
    //    }

    //    if (!isGray && skill.Data["type"] == "1")
    //    {
    //        string[] newStarData = skill.Data["value"].Split(':');
    //        if (newStarData[0] == "1010" && HasExistMusicStar())
    //        {
    //            image += "_1";
    //            isGray = true;
    //        }

    //    }
    //    else if (!isGray && skill.Data["type"] == "5")
    //    {
    //        //判定是否客人正在离开，并且离开后，座位暂时是全空的。
    //        bool isAllSeatEmpty = true;
    //        for (int i = 0; i < seats.Length; i++)
    //        {
    //            if (!seats[i].IsEmptySeat() && !seats[i].IsLeaving)
    //            {
    //                isAllSeatEmpty = false;
    //                break;
    //            }
    //            if (!isAllSeatEmpty)
    //                break;
    //        }

    //        if (isAllSeatEmpty)
    //        {
    //            image += "_1";
    //            isGray = true;
    //        }
    //    }
    //    img.sprite = Resources.Load<Sprite>(image);
    //    img.SetNativeSize();
    //}

    //public IEnumerator ShowMessage(string message)
    //{
    //    if (messageCoroutine != null)
    //    {
    //        StopCoroutine(messageCoroutine);
    //        messageCoroutine = null;
    //    }
    //    messagePanel.transform.localScale = Vector3.zero;
    //    messagePanel.transform.Find("Text").GetComponent<Text>().text = message;
    //    Sequence seq = DOTween.Sequence();
    //    yield return messagePanel.transform.DOScale(Vector3.one, 0.5f).WaitForCompletion();
    //    yield return new WaitForSeconds(1f);
    //    messagePanel.transform.DOScale(Vector3.zero, 0.3f).WaitForCompletion();
    //}

    //public void ResetSkillProgress()
    //{
    //    skillProgress.Reset();
    //    skillProgress.transform.Find("Full").gameObject.SetActive(false);
    //    skillProgress.transform.Find("NotFull").gameObject.SetActive(true);
    //}

    //适配分辨率
    void InitBackground()
    {
        ////替换场景图
        //sceneSprite.sprite = Resources.Load<Sprite>("Background/" + curStage["image"] + "_1");
        //tableSprite.sprite = Resources.Load<Sprite>("Background/" + curStage["image"] + "_2");
        //float height = Camera.main.orthographicSize * 2;
        ////修正Background的坐标，适应分辨率
        //GameObject.FindWithTag("BoxBackground").transform.position = new Vector3(0, (9.6f - height) / 2, 0);
        //for (int i = 0; i < seats.Length; i++)
        //{
        //    Transform wishBox = seats[i].transform.Find("wishBox");
        //    wishBox.position = new Vector3(wishBox.position.x, wishBox.position.y + (Camera.main.orthographicSize * 2 - 9.6f) / 2, wishBox.position.z);
        //}

        ////设置场景遮罩的位置 
        //if (IsGuideStage)
        //{
        //    guideBgClip.transform.position = GameObject.FindWithTag("BoxBackground").transform.Find("scene").position;
        //}
    }

    IEnumerator CheckDebuffTurn()
    {
        if (curStage.OnTurnSpecStars != "0")
        {
            string[] data = curStage.OnTurnSpecStars.Split(',');
            if (debuffIndex >= data.Length)
            {
                //说明所有异常状态已经没了。则隐藏异常回合倒计时
                m_Debuff.SetActive(false);
                yield break;
            }
            //宝石ID：数量：出现回合
            string[] speData = data[debuffIndex].Split(':');
            var starData = ConfigController.Instance.GetConfig<Sys_Star>(int.Parse(speData[0]));
            // 剩余回合
            Text debuffTurnText = m_Debuff.transform.Find("Text").GetComponent<Text>();
            //这种情况只做初始化
            if (!m_Debuff.activeInHierarchy)
            {
                m_Debuff.SetActive(true);
                m_Debuff.GetComponent<Image>().sprite = Resources.Load<Sprite>(starData.Image + "_10");
                debuffTurnText.text = speData[2];
            }
            else
            {
                int leftTurn = int.Parse(debuffTurnText.text);
                leftTurn--;
                debuffTurnText.text = leftTurn.ToString();
                //当前回合，生成宝石
                if (leftTurn == 0)
                {
                    int count = int.Parse(speData[1]);
                    for (int j = 0; j < count; j++)
                    {
                        SpecialStars.Add(starData);
                    }

                    //在0回合等待一下，再跳转到新的DEBUFF
                    yield return new WaitForSeconds(0.6f);
                    //先隐藏当前的
                    m_Debuff.SetActive(false);
                    //等待异常宝石生成完成，则开始显示下一个异常状态倒计时
                    while (SpecialStars.Count > 0)
                    {
                        yield return null;
                    }

                    debuffIndex++;
                    StartCoroutine(CheckDebuffTurn());
                }
            }
        }
    }

    IEnumerator CheckTurn()
    {
        Turn++;
        //turnText.text = (int.Parse(curStage["minRequireTurn"]) - turn).ToString();
        StartCoroutine(m_Girl.PassActionTurn());
        StartCoroutine(CheckDebuffTurn());

        for (int i = 0; i < starTable.GetLength(0); i++)
        {
            for (int j = 0; j < starTable.GetLength(1); j++)
            {
                if (starTable[i, j] != null)
                {
                    //占据多格的宝石，只有本体宝石判定回合，其他3个占位的，不重复进行，否则会这个宝石一次减掉2个或者4个回合
                    if (starTable[i, j].indexOfRow != i || starTable[i, j].indexOfColumn != j)
                        continue;
                    StartCoroutine(starTable[i, j].ChangeTurn());
                }
            }
        }

        while (destroyingStarFlag != 0 || checkingStarTurnFlag != 0
            || generateSpecialStarFlag != 0 || customerLeavingFlag != 0)
        {
            yield return null;
        }

        //if (!isGameOver)
        //{
        //    GameOver();
        //}
    }

    void GameOver()
    {
        isGameOver = true;
        StartCoroutine(ShowGameOver());
    }

    IEnumerator ShowGameOver()
    {
        print("Game Over !");
        yield return new WaitForSeconds(2f);
        //bool isWin = curScore >= int.Parse(maxScoreText.text);
        //int index = isWin ? 1 : 0;
        //resultPanel[index].transform.position = new Vector3(0, Screen.height / 100, 0);
        //resultPanel[index].SetActive(true);
        //resultPanel[index].transform.DOMoveY(0, 0.8f);
        //if (isWin)
        //{
        //    SoundManager.Instance.PauseMusicWhenPlaySound("战斗胜利");
        //    resultPanel[index].transform.Find("title/scoreText").GetComponent<AutoNumber>().AddNum(curScore);
        //    Dictionary<string, int> lastReward = new Dictionary<string, int>();

        //    //额外货币奖励
        //    int rewardCash = (int)(curScore * float.Parse(curStage["rewardCashRate"]));
        //    passStageReward.Add(GlobalData.CASH_CURRENCY + ":" + rewardCash);
        //    //首次通关宝石奖励
        //    if (UserData.Instance.Data.IsFirstPassStage(GlobalData.CUR_LEVEL))
        //    {
        //        passStageReward.Add(curStage["firstRewardDiamond"]);
        //        UserData.Instance.Data.UnLockNextRestaurant(GlobalData.CUR_LEVEL);
        //    }
        //    //整合列表，同样的道具整合到一起
        //    for (int i = 0; i < passStageReward.Count; i++)
        //    {
        //        string[] data = passStageReward[i].Split(':');
        //        if (lastReward.ContainsKey(data[0]))
        //        {
        //            lastReward[data[0]] += int.Parse(data[1]);
        //        }
        //        else
        //        {
        //            lastReward.Add(data[0], int.Parse(data[1]));
        //        }
        //    }

        //    int rewardIndex = 0;
        //    foreach (var data in lastReward)
        //    {
        //        //显示到过关奖励上
        //        rewards[rewardIndex].SetActive(true);
        //        rewards[rewardIndex].GetComponent<Image>().sprite = Resources.Load<Sprite>(GlobalData.GameCfgData[GlobalData.SYS_PROP][int.Parse(data.Key)]["image"]);
        //        rewards[rewardIndex].transform.Find("Text").GetComponent<AutoNumber>().AddNum(data.Value);
        //        //添加到存档
        //        UserData.Instance.Data.AddProp(data.Key + ":" + data.Value);
        //        rewardIndex++;
        //    }

        //    UserData.Instance.Data.UpdateScore(GlobalData.CUR_LEVEL, curScore);
        //}
        //else
        //{
        //    SoundManager.Instance.PauseMusicWhenPlaySound("战斗失败");
        //    resultPanel[index].transform.Find("title/scoreText").GetComponent<Text>().text = curScore + "/" + maxScoreText.text;
        //}
    }

    void MouseOnStar()
    {
        if (starTable != null && canTouch)
        {
            RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
            if (hit.collider != null)
            {
                //Debug.Log("object clicked: "+hit.collider.tag);
                Star star = hit.collider.gameObject.GetComponent<Star>();
                if (star != null)
                {
                    isLinking = true;
                    OnChooseStar(star);
                }

            }

        }
    }

    void ClearStarTable()
    {
        if (starTable != null)
        {
            for (int i = 0; i < starTable.GetLength(0); i++)
            {
                for (int j = 0; j < starTable.GetLength(1); j++)
                {
                    Star pSprite0 = starTable[i, j];
                    if (pSprite0 != null)
                    {
                        pSprite0.JustDestroy();
                        starTable[i, j] = null;
                    }
                }
            }
        }
        starTable = null;
    }

    void InitStarTable()
    {
        ClearStarTable();
        starTable = new Star[numX, numY];

        //先检测初级特殊宝石生成
        if (curStage.InitSpecStars != "0")
        {
            string[] speStarsData = curStage.InitSpecStars.Split(',');
            for (int i = 0; i < speStarsData.Length; i++)
            {
                string[] speStarData = speStarsData[i].Split(':');
                //第一位是宝石ID
                Sys_Star starData = ConfigController.Instance.GetConfig<Sys_Star>(int.Parse(speStarData[0]));
                if (starData == null)
                    continue;

                for (int k = 1; k < speStarData.Length; k++)
                {
                    int pos = int.Parse(speStarData[k]);
                    //策划填写的时候，是从1开始的，而程序上是从0开始的，所以要先减1
                    int row = (pos - 1) / numY;
                    int col = (pos - 1) % numY;
                    if (starTable[row, col] != null)
                        continue;
                    starTable[row, col] = CreateStar(starData, row, col);
                    if (starData.Content != 1)
                    {
                        //占据2格或者4格
                        //右边相邻的
                        starTable[row, col + 1] = starTable[row, col];
                        if (starData.Content == 4)
                        {
                            //4格比2格多两个上方的宝石
                            starTable[row + 1, col] = starTable[row, col];
                            starTable[row + 1, col + 1] = starTable[row, col];
                        }
                    }
                }
            }
        }

        for (int i = 0; i < numX; i++)
        {
            for (int j = 0; j < numY; j++)
            {
                //如果这个位置已经有宝石了，则不生成，因为已经被初级特殊宝石占据了
                if (starTable[i, j] == null)
                {
                    Star pSprite0 = GetRandomStar(i, j);
                    starTable[i, j] = pSprite0;
                }
            }
        }
    }

    void InitBgBlock()
    {
        GameObject b1 = Resources.Load("bgBlock01", typeof(GameObject)) as GameObject;

        Vector3 size = b1.GetComponent<SpriteRenderer>().bounds.size;
        Transform parentBgBlock = transform.FindChild("BgBlocks");
        Vector3 bgBlocksNewPos = Vector3.zero;
        Vector3 parentSize = GetComponent<SpriteRenderer>().bounds.size;
        bgBlocksNewPos.x = -size.x * numY / 2;
        bgBlocksNewPos.y = -parentSize.y / 2;
        parentBgBlock.localPosition = bgBlocksNewPos;
        GameObject blockBg = null;
        bgBlocks = new GameObject[numX, numY];
        for (int i = 0; i < numX; i++)
        {
            for (int j = 0; j < numY; j++)
            {

                if (((i + 1) % 2 == 0 || (j + 1) % 2 == 0) && ((i + 1) % 2 != 0 || (j + 1) % 2 != 0))
                {
                    blockBg = Instantiate(b1);
                }
                else
                {
                    blockBg = Instantiate(b1);
                }


                blockBg.transform.parent = parentBgBlock;
                float x = 0;
                float y = 0.47f;

                x += (size.x + 0.13f) * j;

                y += size.y * i;
                blockBg.transform.localPosition = new Vector3(x, y, 0);
                bgBlocks[i, j] = blockBg;
            }
        }
    }

    Star GetRandomStar(int rowIndex, int colIndex)
    {
        Sys_Star starData = null;
        while (true)
        {
            int index = Random.Range(0, starsColor.Count);
            starData = starsColor[index];
            if (colorCount[starData.Id] < curStage.RandomCount)
                break;
        }

        Star star = CreateStar(starData, rowIndex, colIndex);
        Vector3 newPos = bgBlocks[rowIndex, colIndex].transform.position;
        newPos.y += (star.indexOfRow + 10) * star.size.y;
        star.transform.position = newPos;
        StartCoroutine(star.Fall());
        return star;
    }

    Star CreateStar(Sys_Star starData, int row, int col)
    {
        Star star = Instantiate(Resources.Load<GameObject>("Star")).GetComponent<Star>();
        star.transform.SetParent(transform);
        star.parentSize = transform.GetComponent<SpriteRenderer>().bounds.size;
        star.Init(starData, row, col);
        if (colorCount.ContainsKey(starData.Id))
            colorCount[starData.Id]++;
        return star;
    }

    IEnumerator CreateSpecialStar()
    {
        forbidTouchFlags++;
        while (SpecialStars.Count > 0)
        {
            var specialStarData = SpecialStars[0];
            Star chosenStar = null;
            List<Star> list = new List<Star>();

            //需要置顶生成
            if (specialStarData.CreateOnTop != 0)
            {
                for (int j = 0; j < starTable.GetLength(1); j++)
                {
                    Star star = starTable[numX - 1, j];
                    if (!star)
                        continue;
                    if (star.Data.Erasable == 1 || star.Data.Erasable == 2)
                    {
                        list.Add(star);
                    }
                }
            }
            else
            {
                //选中场上一个基础宝石，替换掉
                for (int i = 0; i < starTable.GetLength(0); i++)
                {
                    for (int j = 0; j < starTable.GetLength(1); j++)
                    {
                        Star star = starTable[i, j];
                        if (!star)
                            continue;
                        if (star.Data.Erasable == 1 || star.Data.Erasable == 2)
                        {
                            if (specialStarData.Content != 1)
                            {
                                //占据2格或者4格
                                //右边的越界，则这个位置不能掉落
                                if (!CatchStar(i, j + 1) || (starTable[i, j + 1].Data.Erasable != 1 && starTable[i, j + 1].Data.Erasable != 2))
                                    continue;
                                if (specialStarData.Content == 4)
                                {
                                    //4格比2格多两个上方的宝石
                                    if (!CatchStar(i + 1, j) || !CatchStar(i + 1, j + 1))
                                        continue;
                                    //上面两个宝石存在，并且，都是1,2类型的，才能算做可以添加
                                    if ((starTable[i + 1, j].Data.Erasable != 1 && starTable[i + 1, j].Data.Erasable != 2)
                                        || (starTable[i + 1, j + 1].Data.Erasable != 1 && starTable[i + 1, j + 1].Data.Erasable != 2))
                                        continue;

                                }
                            }

                            list.Add(star);
                        }



                    }
                }
            }
            if (list.Count > 0)
            {
                chosenStar = list[(int)Random.Range(0, list.Count)];
            }

            if (chosenStar != null)
            {
                yield return StartCoroutine(GenerateSpecailStar(specialStarData, chosenStar));
            }

            SpecialStars.RemoveAt(0);
        }
        forbidTouchFlags--;
    }

    public bool HasExistMusicStar()
    {
        if (starTable == null)
            return false;
        //音符宝石，同时只能一个在场
        for (int i = 0; i < starTable.GetLength(0); i++)
        {
            for (int j = 0; j < starTable.GetLength(1); j++)
            {
                if (starTable[i, j] && starTable[i, j].Data.Erasable == 3)
                {
                    return true;
                }
            }
        }
        return false;
    }

    //每一个对应一个被选中的宝石，顺序生成宝石
    public IEnumerator GenerateSpecailStars(List<Sys_Star> starDatas, List<Star> chosenStars)
    {
        for (int i = 0; i < chosenStars.Count; i++)
        {
            StartCoroutine(GenerateSpecailStar(starDatas[i], chosenStars[i]));
            yield return new WaitForSeconds(0.2f);
        }
    }

    //在一个被选中的宝石上，生成新宝石
    public IEnumerator GenerateSpecailStar(Sys_Star starData, Star chosenStar)
    {
        //音符宝石，同时只能一个在场
        if (starData.Erasable == 3)
        {
            if (HasExistMusicStar())
            {
                yield break;
            }
        }
        generateSpecialStarFlag++;
        int row = chosenStar.indexOfRow;
        int col = chosenStar.indexOfColumn;
        Star newStar = CreateStar(starData, row, col);
        newStar.transform.position = bgBlocks[row, col].transform.position;//chosenStar.transform.position;
        chosenStar.JustDestroy();
        starTable[row, col] = newStar;
        if (starData.Content != 1)
        {
            //占据多格的要修正位置
            newStar.transform.position = newStar.RealPosition();
            starTable[row, col + 1].JustDestroy();
            starTable[row, col + 1] = newStar;
            if (starData.Content == 4)
            {
                starTable[row + 1, col].JustDestroy();
                starTable[row + 1, col] = newStar;
                starTable[row + 1, col + 1].JustDestroy();
                starTable[row + 1, col + 1] = newStar;
            }
        }
        newStar.transform.localScale = new Vector3(3, 3, 3);
        Tweener tweener = newStar.transform.DOScale(new Vector3(1, 1, 1), 0.2f);
        yield return tweener.WaitForCompletion();

        generateSpecialStarFlag--;
    }

    //获取指定坐标的星星，如果没有找到或者越界，就返回null
    Star CatchStar(int row, int col)
    {
        if (row >= starTable.GetLength(0) || row < 0)
            return null;
        if (col >= starTable.GetLength(1) || col < 0)
            return null;
        return starTable[row, col];
    }

    Star GetFallableStar(int i, int j)
    {
        int k = i + 1;
        while (k < starTable.GetLength(0))
        {
            Star upSprite = starTable[k, j];
            if (upSprite != null && upSprite.Data.CanBeDropped == 1)
            {
                if (upSprite.Data.Content == 1)
                {
                    return upSprite;
                }
                //掉落这个位置必须与多格宝石本体在同一列才能掉落，仔细想想为什么
                if (upSprite.indexOfColumn != j)
                {
                    k++;
                    continue;
                }
                //占据多格
                //2或者4，都是判定下面2格是否都为null，才能掉落
                //i,j本身已经是空了,所以需要再判定下相邻的i，j+1是否为空，是空的多格宝石才能掉落
                if (starTable[i, j + 1] == null)
                {
                    if (upSprite.Data.Content == 2)
                        return upSprite;

                    //4格的，掉落还要判定上面一行的两格，是否能掉落过去，如果有冰块上面的，就被会挡住，不能掉落
                    if ((starTable[i + 1, j] == upSprite && starTable[i + 1, j + 1] == upSprite)
                        || (starTable[i + 1, j] == null && starTable[i + 1, j + 1] == null))
                        return upSprite;
                }

            }
            k++;
        }

        return null;
    }

    public IEnumerator FallStar()
    {
        for (int i = 0; i < starTable.GetLength(0); i++)
        {
            for (int j = 0; j < starTable.GetLength(1); j++)
            {
                Star star = starTable[i, j];
                if (star == null)
                {
                    Star fallSprite = GetFallableStar(i, j);
                    if (fallSprite != null)
                    {
                        int fallRow = fallSprite.indexOfRow;
                        int fallCol = fallSprite.indexOfColumn;

                        fallSprite.indexOfRow = i;
                        fallSprite.indexOfColumn = j;
                        starTable[i, j] = fallSprite;
                        starTable[fallRow, fallCol] = null;

                        //是一个占据多格的宝石下落
                        if (fallSprite.Data.Content != 1)
                        {
                            //如果是2类型下落，则只更改相邻的位置也是下落成这一个宝石
                            starTable[i, j + 1] = fallSprite;
                            //原来相邻位置的先清空
                            starTable[fallRow, fallCol + 1] = null;
                            if (fallSprite.Data.Content == 4)
                            {
                                //原来相邻位置的先清空
                                starTable[fallRow + 1, fallCol] = null;
                                starTable[i + 1, j] = fallSprite;
                                //原来相邻位置的先清空
                                starTable[fallRow + 1, fallCol + 1] = null;
                                starTable[i + 1, j + 1] = fallSprite;
                            }
                        }


                        StartCoroutine(fallSprite.Fall());
                    }
                    else
                    {
                        starTable[i, j] = GetRandomStar(i, j);
                    }
                }
            }
        }

        //因为宝石掉落会增加这个标记，所以当这个标记为0的时候，才执行后面的代码
        while (fallingStarFlag != 0)
        {
            yield return null;
        }

        bool needToFall = false;
        //判定最底部的宝石，有下落型宝石，就说明到底了，可以摧毁了
        for (int j = 0; j < starTable.GetLength(1); j++)
        {
            Star star = starTable[0, j];
            if (star != null)
            {
                if (star.Data.CreateOnTop != 0)
                {
                    StartCoroutine(star.Explode());
                    needToFall = true;
                }
            }
        }

        //等待所有宝石都消除掉，因为可能有落到底部的宝石需要自动消除，需要再判定一次下落
        while (destroyingStarFlag != 0)
        {
            yield return null;
        }

        if (needToFall)
        {
            yield return StartCoroutine(FallStar());
        }
    }

    Sys_Star FindTriggerCircle(int linkedLenght)
    {
        Sys_Star triggerCreateStar = null;
        for (int i = 0; i < boomStars.Count; i++)
        {
            if (linkedLenght >= boomStars[i].RequireDestroyNum)
            {
                triggerCreateStar = boomStars[i];
            }
        }

        return triggerCreateStar;
    }

    IEnumerator Link()
    {
        forbidTouchFlags++;
        ClearBoomCircle();
        ClearBoomRange();
        ClearLinkArrows();
        if (starLink.Count >= 3)
        {
            for (int i = 0; i < starLink.Count; i++)
            {
                starLink[i].CancelChoose();
                starLink[i].CancelBoomChoose();
            }

            //检查是否触发特殊宝石生成
            var triggerCreateStar = FindTriggerCircle(starLink.Count);
            //预留最后一个链接位置，用于生成高级宝石
            int lastStarRow = starLink[starLink.Count - 1].indexOfRow;
            int lastStarCol = starLink[starLink.Count - 1].indexOfColumn;

            //一个个的去填充菜品
            List<Star> allDestroyStarList = GetAllCanBeDestroyStars();
            //先循环一次，找出棋盘中间播放的动画应该是哪一个，1004会覆盖1003，所以找到1004就停止循环了
            string boomImgFlag = "";
            bool hasBoom1004 = false;
            for (int i = 0; i < allDestroyStarList.Count; i++)
            {
                if (allDestroyStarList[i].Data.Erasable == 2)
                {
                    switch (allDestroyStarList[i].Data.Id)
                    {
                        case 1003:
                            //闪电，在宝石框正中间放动画,如果正在播放了，就不播放了，闪电优先级比飓风低
                            if (boomImgFlag == "")
                            {
                                boomImgFlag = allDestroyStarList[i].Data.Image;
                            }
                            break;
                        case 1004:
                            //飓风，在宝石框正中间放动画,如果正在放飓风就不放了，如果在放闪电，直接把闪电T了
                            boomImgFlag = allDestroyStarList[i].Data.Image;
                            hasBoom1004 = true;
                            break;
                    }

                    if (hasBoom1004)
                        break;
                }
            }

            destroySoundIndex = 1;
            //结算分数
            m_Player.Attack(allDestroyStarList,starLink);

            for (int i = 0; i < allDestroyStarList.Count; i++)
            {
                yield return StartCoroutine(DestroyStar(allDestroyStarList[i]));
            }


            //等待所有该摧毁的宝石摧毁效果结束
            while (destroyingStarFlag != 0)
            {
                yield return null;
            }

            //如果要生成新宝石，在这里先生成
            if (triggerCreateStar != null)
            {
                Star star = CreateStar(triggerCreateStar, lastStarRow, lastStarCol);
                starTable[lastStarRow, lastStarCol] = star;
                star.transform.position = bgBlocks[lastStarRow, lastStarCol].transform.position;
            }

            //先检查回合，再进行掉落检测，否则某些宝石，比如虫卵会在回合结算处爆炸，但是已经掉落过了，不执行掉落逻辑了 

            yield return StartCoroutine(FallStar());
            //等待触发技能面板隐藏，也就是触发技能都释放完成了，再检查回合
            //while (skillProgress.RealProgress >= 1.0f)
            //    yield return null;
            yield return StartCoroutine(CheckTurn());
            yield return StartCoroutine(FallStar());

        }
        ClearLink();

        forbidTouchFlags--;
    }

    public List<Star> getEightDirectionStars(Star star)
    {
        List<Star> costStars = new List<Star>();
        //下
        Star checkStar = CatchStar(star.indexOfRow - 1, star.indexOfColumn);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }
        //左下
        checkStar = CatchStar(star.indexOfRow - 1, star.indexOfColumn - 1);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }
        //左上
        checkStar = CatchStar(star.indexOfRow + 1, star.indexOfColumn - 1);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }
        //左
        checkStar = CatchStar(star.indexOfRow, star.indexOfColumn - 1);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }
        //上
        checkStar = CatchStar(star.indexOfRow + 1, star.indexOfColumn);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }
        //右下
        checkStar = CatchStar(star.indexOfRow - 1, star.indexOfColumn + 1);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }
        //右上
        checkStar = CatchStar(star.indexOfRow + 1, star.indexOfColumn + 1);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }
        //右
        checkStar = CatchStar(star.indexOfRow, star.indexOfColumn + 1);
        if (checkStar && !costStars.Contains(checkStar))
        {
            costStars.Add(checkStar);
        }

        return costStars;
    }

    List<Star> ListInBoomRangeStars(Star star)
    {
        int id = star.Data.Id;
        List<Star> costStars = new List<Star>();
        switch (id)
        {
            //连接消除以后可以炸掉周围一圈的宝石
            case 1001:
                List<Star> eightStars = getEightDirectionStars(star);
                for (int i = 0; i < eightStars.Count; i++)
                {
                    //掉落型宝石不能被炸掉
                    if (eightStars[i].Data.CreateOnTop == 0)
                    {
                        costStars.Add(eightStars[i]);
                    }
                }
                break;
            //连接消除以后可以炸掉以自己为中心十字范围的宝石，可以穿透冰块。
            case 1002:
                //找出同列的宝石
                for (int i = 0; i < starTable.GetLength(0); i++)
                {
                    Star colStar = starTable[i, star.indexOfColumn];
                    //掉落型宝石不能被炸掉
                    if (colStar && !costStars.Contains(colStar) && colStar.Data.CreateOnTop == 0 && colStar != star)
                    {
                        costStars.Add(colStar);
                    }

                }
                //找出同排的宝石
                for (int j = 0; j < starTable.GetLength(1); j++)
                {
                    Star rowStar = starTable[star.indexOfRow, j];
                    if (rowStar && !costStars.Contains(rowStar) && rowStar.Data.CreateOnTop == 0 && rowStar != star)
                    {
                        costStars.Add(rowStar);
                    }
                }
                break;
            //连接消除以后可以消除场上当前连接的这个种类的宝石，并且随机对场上3个3级宝石造成一次伤害
            case 1003:
            //连接消除以后可以消除场上一个种类的宝石，并且随机对场上6个3级宝石造成一次伤害，随机消除9个其他种类宝石。
            case 1004:
                //先找到主体宝石
                int lastMainStarId = 0;
                for (int i = 0; i < starLink.Count; i++)
                {
                    //是1类型，则算做主体宝石
                    if (starLink[i] && starLink[i].Data.Erasable == 1)
                    {
                        lastMainStarId = starLink[i].Data.Id;
                    }
                }

                for (int i = 0; i < starTable.GetLength(0); i++)
                {
                    for (int j = 0; j < starTable.GetLength(1); j++)
                    {
                        if (starTable[i, j])
                        {
                            //找出所有同样颜色的宝石炸掉
                            if (starTable[i, j].Data.Id == lastMainStarId)
                            {
                                costStars.Add(starTable[i, j]);
                            }
                        }
                    }
                }
                string[] speData = star.Data.ExtValue.Split(',')[0].Split(':');
                int specialStarCount = int.Parse(speData[0]);
                int specialStarDamage = 1;
                if (id == 1004)
                {
                    specialStarDamage = int.Parse(speData[1]);
                }

                List<Star> speStars = GetExistSpecialStars();
                for (int i = speStars.Count - specialStarCount; i > 0; i--)
                {
                    //直接移除最上面的一个
                    speStars.RemoveAt(speStars.Count - 1);
                }

                //造成多次伤害就添加多次
                for (int k = 0; k < specialStarDamage; k++)
                {
                    costStars.AddRange(speStars);
                }

                //如果是1004，则是旋风，旋风会额外寻找9个非当前主体宝石，加入消除列表
                if (id == 1004)
                {
                    int otherMainStarCount = int.Parse(star.Data.ExtValue.Split(',')[1]);
                    //随机对异常宝石伤害一次,取specialStarCount个异常宝石
                    for (int i = 0; i < starTable.GetLength(0); i++)
                    {
                        //跳出整个循环
                        if (otherMainStarCount == 0)
                        {
                            break;
                        }

                        for (int j = 0; j < starTable.GetLength(1); j++)
                        {
                            //跳出整个循环
                            if (otherMainStarCount == 0)
                            {
                                break;
                            }
                            Star speStar = starTable[i, j];
                            if (speStar != null)
                            {
                                //取得固定的其他种类宝石，从左下开始，固定顺序
                                if (!costStars.Contains(speStar) && speStar.Data.Erasable == 1 && speStar.Data.Id != lastMainStarId)
                                {
                                    costStars.Add(speStar);
                                    otherMainStarCount--;
                                }
                            }
                        }
                    }
                }
                break;
        }

        return costStars;
    }

    public IEnumerator DestroyStar(Star destroyStar)
    {
        if (!destroyStar || destroyStar.IsCost)
            yield break;
        //如果是1类型的宝石，才是基础食材，可以被顾客的菜品吸收掉
        if (destroyStar.Data.Erasable == 1)
        {
            SoundManager.Instance.PlaySound("jewel_" + destroySoundIndex);
            destroySoundIndex++;
            if (destroySoundIndex > 8)
                destroySoundIndex = 1;

            yield return new WaitForSeconds(0.06f);
        }
        else if (destroyStar.Data.Erasable == 2)
        {
            destroyStar.CancelChoose();
            destroyStar.CancelBoomChoose();
            switch (destroyStar.Data.Id)
            {
                case 1001:
                    {
                        GameObject boomObj = Instantiate(Resources.Load<GameObject>(destroyStar.Data.Image + "Boom"));
                        boomObj.transform.position = destroyStar.transform.position;
                        SoundManager.Instance.PlaySound("火魔法书");

                        List<Star> boomRangeStars = ListInBoomRangeStars(destroyStar);
                        for (int i = 0; i < boomRangeStars.Count; i++)
                        {
                            if (!boomRangeStars[i] || boomRangeStars[i].IsCost || boomRangeStars[i] == destroyStar)
                                continue;
                            boomRangeStars[i].GushAnimation(destroyStar, 2f);
                        }
                    }
                    break;
                case 1002:
                    {
                        //找到动画对象，克隆4份，因为要朝4个方向喷射   
                        Vector3 basePos = destroyStar.transform.position;
                        for (int i = 0; i < 4; i++)
                        {
                            GameObject obj = Instantiate(Resources.Load<GameObject>(destroyStar.Data.Image + "Boom"));
                            Transform trans = obj.transform;
                            float x = basePos.x;
                            float y = basePos.y;
                            //0上1下2左3右
                            switch (i)
                            {
                                case 0:
                                    trans.position = new Vector3(x, y + 2.4f, 0);
                                    break;
                                case 1:
                                    trans.position = new Vector3(x, y - 2.4f, 0);
                                    trans.rotation = Quaternion.Euler(0, 0, 180);
                                    break;
                                case 2:
                                    trans.position = new Vector3(x - 3.4f, y, 0);
                                    trans.rotation = Quaternion.Euler(0, 0, 90);
                                    break;
                                case 3:
                                    trans.position = new Vector3(x + 3.4f, y, 0);
                                    trans.rotation = Quaternion.Euler(0, 0, 270);
                                    break;
                            }
                        }

                        SoundManager.Instance.PlaySound("蒸汽");
                        List<Star> boomRangeStars = ListInBoomRangeStars(destroyStar);
                        for (int i = 0; i < boomRangeStars.Count; i++)
                        {
                            if (!boomRangeStars[i] || boomRangeStars[i].IsCost || boomRangeStars[i] == destroyStar)
                                continue;
                            boomRangeStars[i].GushAnimation(destroyStar, 2f);
                        }
                    }
                    break;
                case 1003:
                    {
                        List<Star> boomRangeStars = ListInBoomRangeStars(destroyStar);
                        SoundManager.Instance.PlaySound("刀光");

                        for (int i = 0; i < boomRangeStars.Count; i++)
                        {
                            //闪电魔法，给每个宝石被刀光劈砍的效果
                            GameObject flashObj = Instantiate(Resources.Load<GameObject>("SplitAnimation"));
                            flashObj.transform.position = boomRangeStars[i].transform.position;
                            if (i == boomRangeStars.Count - 1)
                            {
                                //yield return StartCoroutine(flashObj.GetComponentInChildren<AnimationFrameEvent>().DestroyOnEnd("Base Layer.Split"));
                            }
                            else
                            {
                               // StartCoroutine(flashObj.GetComponentInChildren<AnimationFrameEvent>().DestroyOnEnd("Base Layer.Split"));
                            }
                        }


                        for (int i = 0; i < boomRangeStars.Count; i++)
                        {
                            if (!boomRangeStars[i] || boomRangeStars[i].IsCost)
                                continue;
                            //给每个宝石一个砍两半的效果
                            boomRangeStars[i].CutSpriteAnimation(1f);
                        }
                    }
                    break;
                case 1004:
                    {
                        List<Star> boomRangeStars = ListInBoomRangeStars(destroyStar);

                        for (int i = 0; i < boomRangeStars.Count; i++)
                        {
                            if (!boomRangeStars[i] || boomRangeStars[i].IsCost)
                                continue;
                            //给每个宝石碎裂飞开的效果
                            boomRangeStars[i].CrushAnimation(1.5f);
                        }
                    }
                    break;
            }
        }

        //如果还是剩下来了这个食材，则直接销毁了
        if (destroyStar){
            StartCoroutine(destroyStar.Explode());
        }
    }

    //IEnumerator RewardItem(Vector3 pos, int itemId, int count)
    //{
    //    GameObject rewardObj = Instantiate(Resources.Load<GameObject>("rewardItem"));
    //    rewardObj.transform.SetParent(GameObject.FindWithTag("UINumbers").transform);
    //    rewardObj.transform.localScale = Vector3.one;
    //    rewardObj.transform.Find("Text").GetComponent<Text>().text = "+" + count;
    //    rewardObj.transform.position = pos;
    //    //替换现在的图片
    //    rewardObj.GetComponent<Image>().sprite = Resources.Load<Sprite>(GlobalData.GameCfgData[GlobalData.SYS_PROP][itemId]["image"]);

    //    yield return rewardObj.transform.DOMoveY(rewardObj.transform.position.y + 0.3f, 1).WaitForCompletion();
    //    Graphic[] fadeList = rewardObj.GetComponentsInChildren<Graphic>();
    //    for (int j = 0; j < fadeList.Length; j++)
    //    {
    //        Tweener tweener = fadeList[j].DOFade(0, 1);
    //        if (j == fadeList.Length - 1)
    //        {
    //            tweener.OnComplete(delegate ()
    //            {
    //                //淡出后摧毁
    //                GameObject.Destroy(rewardObj);
    //            });
    //        }
    //    }
    //    //奖励列表保存，暂时只给显示奖励的效果，但是具体得到必须成功通关后。通关失败会清除奖励
    //    passStageReward.Add(itemId + ":" + count);
    //}

    void ClearLink()
    {
        if (starLink.Count <= 2)
        {
            for (int i = 0; i < starLink.Count; i++)
            {
                if (!starLink[i].IsCost)
                {
                    starLink[i].CancelChoose();
                }
            }
        }
        starLink.Clear();
    }

    //void LinkGuideFinger(List<Vector3> path)
    //{
    //    DOTween.Kill("FingerAnim");
    //    if (path == null || path.Count == 0)
    //    {
    //        fingerAnim.SetActive(false);
    //        return;
    //    }
    //    fingerAnim.SetActive(true);
    //    float time = 1.3f;
    //    Sequence seq = DOTween.Sequence();
    //    seq.SetId("FingerAnim");
    //    fingerAnim.transform.position = path[0];
    //    for (int i = 1; i < path.Count; i++)
    //    {
    //        seq.Append(fingerAnim.transform.DOMove(path[i], time / (path.Count - 1)));
    //    }
    //    seq.OnComplete(delegate ()
    //    {
    //        seq.Restart();
    //    });
    //}

    bool CanAddToLink(Star star)
    {
        //不能被连接
        if (star.Data.Erasable == 0)
        {
            return false;
        }
        //如果已经包含了当前这个星星，就不执行任何操作
        if (starLink.Contains(star))
        {
            return false;
        }
        else
        {
            //if (IsGuideStage)
            //{

            //    switch (guideStep)
            //    {
            //        case 1:
            //            {
            //                star.arrow.GetComponent<ParticleSystemRenderer>().sortingOrder = 21;
            //                //连接23,24,25,19,13,7的肉
            //                if (starLink.Count == 0)
            //                {
            //                    if (star.indexOfRow != 3 || star.indexOfColumn != 1)
            //                    {
            //                        return false;
            //                    }
            //                }
            //            }
            //            break;
            //        case 2:
            //            {
            //                star.arrow.GetComponent<ParticleSystemRenderer>().sortingOrder = 21;
            //                //连接9,10,11,12,6,7,14,21的蔬菜和锅
            //                if (starLink.Count == 0)
            //                {
            //                    if (star.indexOfRow != 1 || star.indexOfColumn != 1)
            //                    {
            //                        return false;
            //                    }
            //                }
            //            }
            //            break;
            //    }
            //}
            //1 食材宝石，同类型的才能消除,2，3没有限制的可以加入列表
            if (star.Data.Erasable == 1)
            {
                //检查链表最后一个宝石
                //如果链表中没有宝石，则这个宝石是可以加入的
                if (starLink.Count > 0)
                {
                    Star lastLinkedStar = starLink[starLink.Count - 1];
                    //如果两者ID不同，也就是不同类型的宝石，则判定是否2,3消除型
                    if (star.Data.Id != lastLinkedStar.Data.Id)
                    {
                        //上一个宝石，要求只能跟同类型的连接
                        if (lastLinkedStar.Data.Erasable == 1)
                        {
                            return false;
                        }
                        //上一个宝石是2类型，可以与这个链接的主体1类型宝石连接，比如都是面粉，连了个2类型，则2类型后面的还是只能连面粉
                        else if (lastLinkedStar.Data.Erasable == 2)
                        {
                            int lastMainStarId = 0;
                            for (int i = 0; i < starLink.Count - 1; i++)
                            {
                                //是1类型，则算做主体宝石
                                if (starLink[i].Data.Erasable == 1)
                                {
                                    lastMainStarId = starLink[i].Data.Id;
                                }
                            }

                            //检查这个2类型的宝石，依次检查与之相邻的宝石，如果都是2，则一直往下找，找到一个非2的宝石
                            //再判定这个宝石是1，还是3,如果是3，则表示有一个回旋针还没被利用，则这次连接可以不连接这个链接的主体宝石
                            bool hasStar3 = false;
                            for (int i = starLink.Count - 2; i >= 0; i--)
                            {
                                //寻找相邻位置找到了 1类型 则，说明没有回旋针可以生效
                                if (starLink[i].Data.Erasable == 1)
                                {
                                    break;
                                }
                                else if (starLink[i].Data.Erasable == 3)
                                {
                                    hasStar3 = true;
                                    break;
                                }
                                //如果是类型2，则循环继续往下找
                            }

                            //如果没有回旋针，则需要判定是否是连接的同类型的主体宝石
                            if (!hasStar3)
                            {
                                //当前选中的宝石与主体宝石不是同一种，则不能消除
                                //如果2号宝石是第一个宝石 lastMainStarId != ""，那么不用判定是否类型相同了，直接添加进去
                                if (lastMainStarId != 0 && star.Data.Id != lastMainStarId)
                                {
                                    return false;
                                }
                            }
                        }
                        //上一个宝石是3类型，回旋针,则可以选择一个任意颜色连接
                        else if (lastLinkedStar.Data.Erasable == 3)
                        {

                        }
                    }
                }

            }

            //检查是否最后一个宝石的8方向
            if (starLink.Count > 0)
            {
                //判定是否相邻8个方面的
                Star lastStar = starLink[starLink.Count - 1];
                if (Mathf.Abs(lastStar.indexOfColumn - star.indexOfColumn) > 1 || Mathf.Abs(lastStar.indexOfRow - star.indexOfRow) > 1)
                {
                    return false;
                }
            }
        }

        return true;
    }

    void ClearLinkArrows()
    {
        for (int i = 0; i < starLink.Count - 1; i++)
        {
            if (starLink[i])
            {
                starLink[i].arrow.gameObject.SetActive(false);
            }
        }
    }

    void ResetLinkArrows()
    {
        //大于等于二连了，应该用箭头动画连接每个宝石了
        if (starLink.Count >= 2)
        {
            for (int i = 0; i < starLink.Count - 1; i++)
            {
                if (starLink[i] == null)
                    continue;
                ShowLink(starLink[i], starLink[i + 1]);
            }
        }

        //最后一个元素，没有箭头效果
        if (starLink.Count >= 1)
        {
            starLink[starLink.Count - 1].arrow.gameObject.SetActive(false);
        }
    }

    void ShowLink(Star fromStar, Star toStar)
    {
        Vector3 orgPos = fromStar.transform.position;
        Vector3 targetPos = toStar.transform.position;
        int direction = 1;
        if (fromStar.indexOfRow > toStar.indexOfRow)
        {
            direction = -1;
        }
        float angle = Mathf.Acos(Vector3.Dot((targetPos - orgPos).normalized, Vector3.right)) * Mathf.Rad2Deg * direction;
        //因为链接特效是粒子特效，粒子发射器本身是与Y轴同方向的。所以要先减去90度，才是正确的旋转角度
        fromStar.arrow.transform.localRotation = Quaternion.Euler(0, 0, angle - 90);
        fromStar.arrow.gameObject.SetActive(true);
    }

    //完全清除爆炸范围的特效
    void ClearBoomRange()
    {
        for (int i = 0; i < numX; i++)
        {
            for (int j = 0; j < numY; j++)
            {
                boomRangeSpritesCount[i, j] = 0;
                if (boomRangeSprites[i, j] != null)
                {
                    starTable[i, j].isCheckBoom = false;
                    starTable[i, j].CancelBoomChoose();
                    Destroy(boomRangeSprites[i, j]);
                    boomRangeSprites[i, j] = null;
                }
            }
        }
    }

    //pos ： 生成圆圈的坐标
    void CheckBoomCircle(int linkedLength, Vector3 pos)
    {
        //检查是否触发特殊宝石生成
        var triggerCreateStar = FindTriggerCircle(linkedLength);
        if (triggerCreateStar != null)
        {
            int key = triggerCreateStar.RequireDestroyNum;
            //如果包含了，则说明，已经有这个对象了，则不生成
            if (!boomCircleDic.ContainsKey(key))
            {
                ClearBoomCircle();
                GameObject circleParticle = Instantiate(Resources.Load<GameObject>(triggerCreateStar.Image + "CirclePrt"));
                circleParticle.transform.position = pos;
                boomCircleDic.Add(key, circleParticle);
            }
            //如果已经有了，则不再重新生成特效，但是要改变坐标位置到当前这个宝石的位置
            else
            {
                boomCircleDic[key].transform.position = pos;
            }
        }
        else
        {
            //如果里面有对象，说明是旧的效果，需要移除
            ClearBoomCircle();
        }
    }

    void ClearBoomCircle()
    {
        //如果里面有对象，说明是旧的效果，需要移除
        if (boomCircleDic.Count > 0)
        {
            foreach (var data in boomCircleDic)
            {
                Destroy(data.Value);
            }
            boomCircleDic.Clear();
        }
    }

    //生成爆炸范围特效
    void CheckBoomRangeSprite(Star star)
    {
        if (star.Data.Erasable != 2 || star.isCheckBoom)
        {
            return;
        }

        List<Star> rangeList = ListInBoomRangeStars(star);
        if (rangeList.Count > 0)
        {
            star.isCheckBoom = true;
        }
        for (int i = 0; i < rangeList.Count; i++)
        {
            SetBoomRangeSprite(rangeList[i].indexOfRow, rangeList[i].indexOfColumn);

            //多格宝石，占据的位置都要一起亮
            if (rangeList[i].Data.Content != 1)
            {
                SetBoomRangeSprite(rangeList[i].indexOfRow, rangeList[i].indexOfColumn + 1);
                if (rangeList[i].Data.Content == 4)
                {
                    SetBoomRangeSprite(rangeList[i].indexOfRow + 1, rangeList[i].indexOfColumn);
                    SetBoomRangeSprite(rangeList[i].indexOfRow + 1, rangeList[i].indexOfColumn + 1);
                }
            }
            //被爆炸选中，不播放选中边框
            rangeList[i].BoomChoose();
            //检查连锁反应的爆炸效果,占据1格的宝石
            CheckBoomRangeSprite(rangeList[i]);
        }

    }

    void SetBoomRangeSprite(int row, int col)
    {
        GameObject boomRangeSprite = boomRangeSprites[row, col];
        //如果不为空，则说明已经在一个爆炸范围内了，不重复标记
        if (boomRangeSprite == null)
        {
            boomRangeSprite = Instantiate(Resources.Load<GameObject>("boomRangeSprite"));
            boomRangeSprite.transform.position = bgBlocks[row, col].transform.position;
            boomRangeSprites[row, col] = boomRangeSprite;
        }
        //被炸弹覆盖的标记+1，这个标记为0，则爆炸特效对象会完全清除
        boomRangeSpritesCount[row, col]++;
    }

    //获得此次能被消除的所有宝石
    public List<Star> GetAllCanBeDestroyStars()
    {
        List<Star> allCanBeDestroyStars = new List<Star>();
        for (int i = 0; i < starLink.Count; i++)
        {
            AddToCanBeDestroyList(allCanBeDestroyStars, starLink[i]);
        }
        return allCanBeDestroyStars;
    }

    void AddToCanBeDestroyList(List<Star> allCanBeDestroyStars, Star star)
    {
        //不能被炸掉的宝石，不添加进去
        if (star.Data.CanBeBombed == 0)
            return;
        //血量为1，并且已经包含了，不添加进去。不添加进去很重要，否则下面会递归死循环。
        //所以，炸弹一定不能有多血量，否则这里要重新设计
        if (star.IsLastHp && allCanBeDestroyStars.Contains(star))
            return;
        allCanBeDestroyStars.Add(star);

        if (star.Data.Erasable == 2)
        {
            List<Star> costStars = ListInBoomRangeStars(star);
            //爆炸掉的宝石，递归
            for (int j = 0; j < costStars.Count; j++)
            {
                AddToCanBeDestroyList(allCanBeDestroyStars, costStars[j]);
            }
        }
    }

    void OnChooseStar(Star star)
    {
        if (CanAddToLink(star))
        {
            SoundManager.Instance.PlaySound("连接宝石");
            starLink.Add(star);
            ResetLinkArrows();
            //大于等于三连了，则可以消除了，星星变效果
            if (starLink.Count >= 3)
            {
                if (starLink.Count == 3)
                {
                    SoundManager.Instance.PlaySound("连接3个宝石");
                    for (int i = 0; i < starLink.Count - 1; i++)
                    {
                        //这里不要调用choose方法，会增加选中标记，这里直接变换图标就行了
                        starLink[i].ToErasable();
                    }
                }
                star.Choose(true);
                CheckBoomCircle(starLink.Count, star.transform.position);
                //如果是个爆炸方块，则要把周围的方块，标记爆炸,如果还没被选中，则也要播放不包含选中框的可消除效果

                //这个情况下，要检测前面两个，是否有爆炸宝石，有的话，补上特效
                for (int i = 0; i < starLink.Count; i++)
                {
                    CheckBoomRangeSprite(starLink[i]);
                }
            }
            else
            {
                star.Choose(false);
            }

        }
        //如果不能添加
        else
        {
            //如果是链条中的某一个星星，则是回连到此处
            if (starLink.Contains(star) && star != starLink[starLink.Count - 1])
            {
                SoundManager.Instance.PlaySound("连接宝石");
                int index = starLink.IndexOf(star);
                //移除多余的
                while (starLink.Count > index + 1)
                {
                    starLink[starLink.Count - 1].CancelChoose();
                    starLink.RemoveAt(starLink.Count - 1);
                }


                //先清除所有的消除特效，重新生成
                ClearBoomRange();
                CheckBoomCircle(starLink.Count, star.transform.position);

                //重新生成链接特效
                for (int i = 0; i < starLink.Count; i++)
                {
                    starLink[i].CancelChoose();
                    starLink[i].CancelBoomChoose();
                    //大于3个宝石才检测炸弹效果
                    if (starLink.Count >= 3)
                    {
                        CheckBoomRangeSprite(starLink[i]);
                        starLink[i].Choose(true);
                    }
                    else
                    {
                        starLink[i].Choose(false);
                    }
                }

                ResetLinkArrows();
            }

        }
    }

    ////进度满了，触发一次技能
    //public void OnTriggerSkillProgressFull(float progress)
    //{
    //    if (progress >= 1.0f)
    //    {
    //        StartCoroutine(TriggerSkill());
    //    }
    //}

    //IEnumerator TriggerSkill()
    //{
    //    if (isGameOver)
    //        yield break;
    //    skillProgress.transform.Find("NotFull").gameObject.SetActive(false);
    //    Transform fullTransform = skillProgress.transform.Find("Full");
    //    fullTransform.gameObject.SetActive(true);
    //    Sequence seq = DOTween.Sequence();
    //    SoundManager.Instance.PlaySound("能量满");
    //    seq.Append(fullTransform.DOScale(new Vector3(2.5f, 2.5f, 2.5f), 0.3f));
    //    seq.Append(fullTransform.DOScale(Vector3.one, 0.2f));
    //    seq.OnComplete(delegate ()
    //    {

    //        for (int i = 0; i < triggerSkills.Length; i++)
    //        {
    //            CheckSkillUseful(triggerSkills[i]);
    //        }

    //        triggerSkillPanel.SetActive(true);
    //    });
    //}

    public List<Star> GetExistSpecialStars()
    {
        List<Star> speStars = new List<Star>();
        if (starTable == null)
            return speStars;
        for (int i = 0; i < starTable.GetLength(0); i++)
        {
            for (int j = 0; j < starTable.GetLength(1); j++)
            {

                Star speStar = starTable[i, j];
                if (speStar != null)
                {
                    //抽取specialStarCount个异常宝石,依次抽取，固定顺序，避免玩家通过取消来随机抽取想要的宝石炸掉，加入消除列表中
                    //置顶宝石，无法被炸掉
                    if (!speStars.Contains(speStar) && speStar.Data.Erasable == 0 && speStar.Data.CanBeBombed == 1)
                    {
                        speStars.Add(speStar);
                    }
                }
            }
        }

        return speStars;
    }
}
